package javapop.framework.parser;

import javapop.framework.Grammar;
import javapop.framework.ParseContext;
import javapop.framework.ParseInput;
import javapop.framework.ParseResult;
import javapop.framework.Parser;

public class Ref<T> extends Parser<T> {
	private Grammar grammar;
	private String ref;
	
	public Ref(Grammar grammar, String ref) {
		if(grammar==null)
			throw new IllegalArgumentException("Null grammar");
		if(ref==null)
			throw new IllegalArgumentException("Null reference");
		
		this.grammar = grammar;
		this.ref = ref;
	}
	
	@Override
	public String getDescription() {
		StringBuffer buf = new StringBuffer();
		buf.append("<");
		buf.append(ref);
		buf.append(">");
		return buf.toString();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public ParseResult<T> eval(ParseContext ctx, ParseInput input) {
		Parser<T> parser = (Parser<T>) grammar.fetch(ref);
		if(parser==null) {
			throw new Error("Unknown reference '"+ref+"' in grammar");
		}
		return parser.parse(ctx, input);
	}
	
	@Override
	public boolean isMemoized() {
		return true;
	}
	
	@Override
	public int hashCode() {
		return ref.hashCode();
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj==null) return false;
		if(obj==this) return true;
		if(obj.getClass()!=this.getClass())
			return false;
		Ref<?> robj = (Ref<?>) obj;
		return robj.grammar==grammar && robj.ref.equals(ref);
	}
	
}
